package com.joelemon.mockinfluxdbdata.datamock.v1;

import lombok.Data;
import lombok.val;

import java.math.BigDecimal;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Description: 取值策略
 * @Author: HJY
 * @Date: 2023/11/14
 */
@Data
public class ValueStrategy {
    // 运行时变量
    private BigDecimal val;
    private BigDecimal max;
    private BigDecimal min;
    private BigDecimal baseVal;
    private BigDecimal fixedVal;
    private BigDecimal fixedRate;
    private BigDecimal atomRandomMax;
    private ChangeType changeType;

    private Random random = new Random();

    public boolean check() {
        return baseVal != null && changeType != null &&
                !(ChangeType.INCREASE.equals(changeType) && max == null) && !(ChangeType.DECREASE.equals(changeType) && min == null);
    }

    private BigDecimal getAtomVal() {
        if (fixedVal != null) {
            return fixedVal;
        }
        if (fixedRate != null) {
            if (val == null) {
                return fixedRate.multiply(baseVal);
            } else {
                return fixedRate.multiply(val);
            }
        }
        if (atomRandomMax != null) {
            return atomRandomMax.multiply(new BigDecimal(random.nextDouble()));
        }
        return BigDecimal.ZERO;
    }

    public BigDecimal getValue() {
        if (!check()) {
            return null;
        }
        if (val == null)
            val = baseVal;
        switch (changeType) {
            case INCREASE -> {
                BigDecimal atomVal = getAtomVal();
                BigDecimal resultVal = val.add(atomVal);
                if (resultVal.compareTo(max) > 0) {
                    val = baseVal;
                } else {
                    val = resultVal;
                }
            }
            case DECREASE -> {
                BigDecimal atomVal = getAtomVal();
                BigDecimal resultVal = val.subtract(atomVal);
                if (resultVal.compareTo(min) < 0) {
                    val = baseVal;
                } else {
                    val = resultVal;
                }
            }
            case RANDOM -> {
                if (random.nextDouble() > 0.5) {
                    val = baseVal.add(max.subtract(baseVal).multiply(new BigDecimal(random.nextDouble())));
                } else {
                    val = baseVal.add(baseVal.subtract(min).multiply(new BigDecimal(random.nextDouble())));
                }
            }
        }
        return val;
    }
}
